package com.itheima.utils;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.rest.RestStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author: CV大师 yuan_he_song
 * @date: 2021年7月16日15:42:50
 * @description: 天下风云出我辈
 */
@Slf4j
@Component
public class ElasticsearchUtil {

    @Autowired
    private RestHighLevelClient client;


    /**
     * 创建索引(包括映射)
     */
    private Boolean createIndexAndMapping(String indexName, Map<String, Object> source) throws Exception {
        if (indexIsExist(indexName)) {
            deleteIndex(indexName);
        }

        CreateIndexRequest request = new CreateIndexRequest(indexName);
        request.setTimeout(TimeValue.timeValueSeconds(2));

        // 设置分片和副本
        request.settings(Settings.builder()
                .put("index.number_of_shards", 5)
                .put("index.number_of_replicas", 1)
        );

        // 创建映射
        request.mapping(source);
        CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
        return response.isAcknowledged();
    }

    /**
     * 删除索引
     */
    public Boolean deleteIndex(String indexName) throws Exception {
        DeleteIndexRequest request = new DeleteIndexRequest(indexName);
        AcknowledgedResponse response = client.indices().delete(request, RequestOptions.DEFAULT);
        return response.isAcknowledged();
    }

    /**
     * 索引是否存在
     */
    public Boolean indexIsExist(String indexName) throws Exception {
        GetIndexRequest request = new GetIndexRequest(indexName);
        return client.indices().exists(request, RequestOptions.DEFAULT);
    }

    /**
     * @Description: 向索引库添加一个文档
     * @param index 索引名称
     * @param document 文档内容
     * @param id 文档id (一般是数据库id)
     * @Author: yuan_he_song
     */
    public Boolean addDoc(String index, Object document, String id) throws Exception {
        if (!indexIsExist(index)) {
            createIndexAndMapping(index, createMapping());
        }
        IndexRequest indexRequest = new IndexRequest(index);
        indexRequest.id(id); // 文档id
        indexRequest.timeout(TimeValue.timeValueSeconds(5));
        indexRequest.source(JSON.toJSONString(document), XContentType.JSON);

        Map<String, Object> doccument = getDoc(index, id);
        if (CollectionUtils.isEmpty(doccument)) {
            IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT);
            return response.status().getStatus() == RestStatus.CREATED.getStatus();
        } else {
            log.warn("索引:{},文档id:{}对应的数据已存在!");
        }
        return false;
    }

    /**
     * @Description: 更新文档
     * @param index 索引名称
     * @param document 文档内容
     * @param id 文档id (一般是数据库id)
     * @Author: yuan_he_song
     */
    public Boolean updateDoc(String index, Object document, String id) throws Exception {
        UpdateRequest request = new UpdateRequest(index, id);
        request.doc(JSON.toJSONString(document), XContentType.JSON);
        UpdateResponse update = client.update(request, RequestOptions.DEFAULT);
        return update.status().getStatus() == RestStatus.OK.getStatus();
    }

    /**
     * @Description: 根据ID获取索引库当前文档信息
     * @param index 索引
     * @param docId 文档id
     */
    public Map<String, Object> getDoc(String index, String docId) throws Exception {
        GetRequest request = new GetRequest(index, docId);
        GetResponse response = client.get(request, RequestOptions.DEFAULT);
        return response.getSourceAsMap();
    }

    /**
     * 搜索
     */
    public SearchResponse search(SearchRequest searchRequest) {
        SearchResponse searchResponse = null;
        try {
            searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error("请求搜索异常:{}", e);
        }
        return searchResponse;
    }

    /**
     * @Description: 根据ID删除当前索引的文档信息
     * @param index 索引
     * @param id  文档id
     */
    public Boolean deleteDocById(String index, String id) throws IOException {
        DeleteRequest request = new DeleteRequest(index, id);
        DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
        return response.status().getStatus() == RestStatus.OK.getStatus();
    }


    /**
     * 创建商品规则映射
     */
    private Map<String, Object> createMapping(){

        Map<String, Object> properties = Maps.newHashMap();

        // 文档_id = 商品id + 批号

        // 商品id
        Map<String, Object> productId = new HashMap<>();
        productId.put("type", "long");
        properties.put("productId", productId);

        // 商城来源 (1:一号商城 2:二号商城 3:盛星商城)
        Map<String, Object> store = new HashMap<>();
        store.put("type", "long");
        properties.put("store", store);

        // 批号
        Map<String, Object> lotNumber = new HashMap<>();
        lotNumber.put("type", "keyword");
        properties.put("lotNumber", lotNumber);

        // 商品名称
        Map<String, Object> productName = new HashMap<>();
        productName.put("type", "keyword");
        properties.put("productName", productName);

        // 商品大分类
        Map<String, Object> bigCategoryId = new HashMap<>();
        bigCategoryId.put("type", "long");
        properties.put("bigCategoryId", bigCategoryId);

        // 商品二级分类(子分类)
        Map<String, Object> smallCategoryId = new HashMap<>();
        smallCategoryId.put("type", "long");
        properties.put("smallCategoryId", smallCategoryId);

        // 商品大分类名称
        Map<String, Object> bigCategoryName = new HashMap<>();
        bigCategoryName.put("type", "keyword");
        properties.put("bigCategoryName", bigCategoryName);

        // 商品大分类名称
        Map<String, Object> smallCategoryName = new HashMap<>();
        smallCategoryName.put("type", "keyword");
        properties.put("smallCategoryName", smallCategoryName);

        // 销售数量 (2号是件, 1号是盒/个)
        Map<String, Object> salesNum = new HashMap<>();
        salesNum.put("type", "long");
        properties.put("salesName", salesNum);

        // 单价(每件/每盒的价格)
        Map<String, Object> price = new HashMap<>();
        price.put("type", "double");
        properties.put("price", price);


        Map<String, Object> mapping = new HashMap<>();
        mapping.put("properties", properties);

        return mapping;
    }
}
